parser grammar AnalexParser;

options {
  language = Java;
  tokenVocab = AnalexLexer;
}

@header {
  package Practica8.Sintactico;
}

@members {
  java.util.Hashtable variables = new java.util.Hashtable();
  private ArrayList<String> errors = new ArrayList<String>();
  public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
    String hdr = getErrorHeader(e);
    String msg = getErrorMessage(e, tokenNames);
    errors.add(hdr + " " + msg);
  }
   
  public ArrayList<String> getErrors() {
    return errors;
  }
}

entrada: (sentencias)*;

sentencias
  : asignacion
  | sentencia;
  
asignacion: v = ID OP_ASSIGN e = expr SEPARADOR { 
	ArithmeticException ae = $e.ae;
	int resultado = $e.res;
	if (ae == null)
	  variables.put(v.getText(),new Integer(resultado));
	System.out.println("Asignacion(" + v.getText() + ") => " + ((Integer)variables.get(v.getText())).intValue());
};  

sentencia
  : e = expr SEPARADOR  { System.out.println ("Expresion: " + e.res); };
  
expr returns [int res = 0, ArithmeticException ae = null]
  : e1 = exp_mult { $res = e1.res; $ae = e1.ae; }
  ((OP_SUM e2 = exp_mult  { $res += e2.res; $ae = e2.ae; })
  |(OP_SUB e2 = exp_mult  { $res -= e2.res; $ae = e2.ae; }))*;
  
exp_mult returns [int res = 0, ArithmeticException ae = null]
  : e1 = exp_base { $res = e1.res; $ae = e1.ae; }
  ((OP_MULT e2 = exp_base  { $res = $res * e2.res; $ae = e2.ae; })
  |(OP_DIV  e2 = exp_base  { $res = $res / e2.res; $ae = e2.ae; }))*;
  catch [ArithmeticException except] {
    System.out.println("División por cero");
    $ae = except;
}

exp_base returns [int res = 0, ArithmeticException ae = null]
  : n = NUMERO  { $res = new Integer(n.getText()).intValue(); }
  | v = ID {   
      if (variables.get(v.getText()) != null) 
        $res = ((Integer)variables.get(v.getText())).intValue(); 
      else 
        $res = 0; 
    }
  | LEFT_PAREN e=expr RIGHT_PAREN 
    { 
      $res = e.res;
      $ae = e.ae; 
};

